package com.huiquan.section.service;

import com.huiquan.analysis.domain.User;
import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.dao.StaticDataDao;
import com.huiquan.framework.domain.StaticData;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.RespHeaderUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.section.dao.SectionCodeDao;
import com.huiquan.section.dao.SectionDao;
import com.huiquan.section.domain.Section;
import com.huiquan.section.domain.SectionCode;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

@Service
public class SectionCodeService extends BaseService {

    @Autowired
    private SectionCodeDao sectionCodeDao;
    @Autowired
    private SectionDao sectionDao;
    @Autowired
    private StaticDataDao staticDataDao;

    public ModelAndView list(String startStr, String nameKey, String exactSearchFlag, String countPerPageStr, String sectionSearch, String code) {

        Map<String, Object> param = new HashMap<>();
        if (nameKey != null && !nameKey.isEmpty()) {
            if (exactSearchFlag != null && exactSearchFlag.equals("1")) {
                param.put("sectionName", nameKey);
            } else {
                param.put("sectionName", "%" + nameKey + "%");
            }
        }
        if (sectionSearch != null && !sectionSearch.isEmpty()) {
            if (exactSearchFlag != null && exactSearchFlag.equals("1")) {
                param.put("section", sectionSearch);
            } else {
                param.put("section", "%" + sectionSearch + "%");
            }
        }
        if (code != null && !code.isEmpty()) {
            if (exactSearchFlag != null && exactSearchFlag.equals("1")) {
                param.put("sectionCode", code);
            } else {
                param.put("sectionCode", "%" + code + "%");
            }
        }
        int totalSize = sectionCodeDao.retrieveSize(param);

        Map<String, Integer> pageNo;
        if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
            int countPerPage = Integer.parseInt(countPerPageStr);
            pageNo = GetListUtil.getPageNoParam(totalSize, startStr, countPerPage);
            param.put("countPerPage", countPerPage);
        } else {
            pageNo = GetListUtil.getPageNoParam(totalSize, startStr);
        }
        int endPage = pageNo.get("endPage");
        int start = pageNo.get("start");
        int startIndex = pageNo.get("startIndex");

        List<SectionCode> list = new ArrayList<>();

        if (startIndex < totalSize) {
            param.put("startIndex", startIndex);
            list = sectionCodeDao.retrievesList(param);
        }

        Map<String, String> showSearch = new LinkedHashMap<>();
        showSearch.put("nameKey", "科室标准词");
        showSearch.put("section", "科室名称");
        showSearch.put("code", "code");

        Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, null);
        //查询是否含有新增了同义词但没有新增其他的科室图片之类的
        List<StaticData> sds = staticDataDao.retrieveByCode("SECTION_ADD_WARN");
        List<StaticData> warnList = new ArrayList<>();
        if (sds != null && sds.size() > 0) {
            for (StaticData sd : sds) {
                warnList.add(sd);
            }
        }
        if (warnList.size() > 0) {
            map.put("warn", "1");
            map.put("warnList", warnList);
        }
        map.put("showSearch", showSearch);

        return new ModelAndView("section/index", map);
    }

    public ModelAndView edit(String id) {
        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isNotBlank(id)) {
            Map<String, Object> param = new HashMap<>();
            param.put("id", id);
            SectionCode value = sectionCodeDao.retrieveObjectById(Long.parseLong(id));
            if (value != null) {
                map.put("std", value.getStd());
                map.put("sectionCode", value.getSectionCode());
                map.put("id", value.getId());
                map.put("sectionName", value.getSectionId());
            }

        }
        return new ModelAndView("section/section_code_edit", map);
    }

    public ModelAndView deleteSectionCode(String id, String startStr, String nameKey, String exactSearchFlag, String countPerPageStr, String sectionSearch, String code) {

        SectionCode sc = new SectionCode();
        sc.setId(Long.parseLong(id));
        sectionCodeDao.delete(sc);
        return list(startStr, nameKey, exactSearchFlag, countPerPageStr, sectionSearch, code);

    }

    public ReturnData sectionCodeAdd(String id, String sectionCode, String std, String sectionName, String changeFlag, User user) {
        String warnMsg = "";
        //校验code是否重复
        if (StringUtils.isNotBlank(sectionCode)) {
            Map<String, Object> param = new HashMap<>();
            param.put("sectionCode", sectionCode);
            if (StringUtils.isNotBlank(id)) {
                param.put("withoutId", id);
            }
            List<SectionCode> sc = sectionCodeDao.retrievesList(param);
            if (sc != null && sc.size() > 0) {
                Map<String, Object> map = new HashMap<>();
                ReturnCode returnCode = ReturnCode.DYNAMIC_DESC_EXCEPTION;
                returnCode.setDesc("该code已经存在");
                return new ReturnData(returnCode, map);
            }
        }
        List<Section> sts = sectionDao.retrieveList();
        Map<String, Long> ksNameAndSectionId = new HashMap<>();
        //获取所有已经存在的科室名称对应编号
        for (Section st : sts) {
            ksNameAndSectionId.put(st.getName(), st.getId());
        }
        //新增
        if (StringUtils.isBlank(id)) {
            SectionCode sc = new SectionCode();
            sc.setModifierId(user.getUserId() + "");
            sc.setSectionCode(sectionCode);
            sc.setStd(std);
            if (StringUtils.isBlank(sectionName)) {
                sc.setSectionId("0");
            } else if (ksNameAndSectionId.get(sectionName) != null) {
                sc.setSectionId(ksNameAndSectionId.get(sectionName) + "");
            } else {
                //不存在需要新增
                Section value = new Section();
                value.setCnt(1);
                value.setDisable("0");
                value.setModifierId(user.getUserId());
                value.setName(sectionName);
                value.setSexAgeFlag(0);
                value.setSex(0);
                value.setAge("");
                Long sectionId = sectionDao.insert(value);
                ksNameAndSectionId.put(sectionName, sectionId);
                sc.setSectionId(sectionId + "");
            }
            sectionCodeDao.insert(sc);
        } else {
            //修改
            SectionCode sc = sectionCodeDao.retrieveObjectById(Long.parseLong(id));
            String oldSection = ksNameAndSectionId.get(sc.getSectionId()) + "";
            String newSection = "";
            sc.setModifierId(user.getUserId() + "");
            sc.setSectionCode(sectionCode);
            if (StringUtils.isBlank(sectionName)) {
                sc.setSectionId("0");
                newSection = "0";
            } else if (ksNameAndSectionId.get(sectionName) != null) {
                sc.setSectionId(ksNameAndSectionId.get(sectionName) + "");
                newSection = ksNameAndSectionId.get(sectionName) + "";
            } else {
                //不存在需要新增
                Section value = new Section();
                value.setCnt(1);
                value.setDisable("0");
                value.setModifierId(user.getUserId());
                value.setName(sectionName);
                value.setSexAgeFlag(0);
                value.setSex(0);
                value.setAge("");
                Long sectionId = sectionDao.insert(value);
                ksNameAndSectionId.put(sectionName, sectionId);
                sc.setSectionId(sectionId + "");
                newSection = sectionId + "";
            }
            sc.setStd(std);
            //更新所有的相同的科室名称
            sectionCodeDao.update(sc);
            //更新所有相同科室名称的记录到新的科室名称
            if (StringUtils.equals(changeFlag, "1")) {
                sectionCodeDao.updateNewSection(oldSection, newSection, user.getUserId());
            }
        }
        //校验国家对应科室是否在科室图片名称中
        checkData();
        //如果失败,删除有可能添加的section的记录
        sectionDao.deleteSectionInvalid();
        return ReturnUtil.success(warnMsg);
    }

    private void checkData() {
        //校验国家对应科室是否在科室图片名称中
        List<SectionCode> checkCode = sectionCodeDao.checkSectionCodeAndImage();
        StringBuffer errCodeList = new StringBuffer();
        if (checkCode != null && checkCode.size() > 0) {
            for (SectionCode sc : checkCode) {
                if (errCodeList.length() == 0) {
                    errCodeList.append("以下国家标准对应科室不在科室图片的科室名称中");
                }
                errCodeList.append(sc.getSectionId() + ";");
            }
        }
        if (errCodeList.length() > 0) {
            throw new RuntimeException(errCodeList.toString());
        }
    }


    public void export(HttpServletResponse resp) throws Exception {
        Map<String, Object> param = new HashMap<>();
        // 获取已校验code列表
        List<SectionCode> sectionList = sectionCodeDao.retrievesList(param);
        // 设置respons的头信息
        RespHeaderUtil.setXlsxResp(resp, "国家标准科室");

        Workbook workbook = new XSSFWorkbook(); // 创建文档

        Sheet sheet = workbook.createSheet("国家标准科室"); // 创建Sheet
        int i = 0;
        // 循环写入数据
        for (SectionCode section : sectionList) {

            Row row = sheet.createRow(i);

            // 如果是小词同义词中有标准词的，则需要将标准词放在每行的第一格；如果标准词不存在则空,英文标准词同样操作
            Cell cell = row.createCell(0);
            cell.setCellValue(section.getSectionCode());

            cell = row.createCell(1);
            cell.setCellValue(section.getStd());

            cell = row.createCell(2);
            cell.setCellValue(section.getSectionId());
            i++;
        }

        OutputStream os = resp.getOutputStream();
        workbook.write(os);

        os.close();
        workbook.close();
    }

    private String getCellNum(Row row, int num) {
        Cell cell = row.getCell(num);
        String index = "";
        if (cell != null) {
            cell.setCellType(Cell.CELL_TYPE_STRING);
            index = cell.getStringCellValue().trim();
        }
        return index;
    }

    /**
     * 批量导入
     *
     * @param user
     * @return
     * @throws IOException
     */
    public ReturnData insertBatch(User user, MultipartFile file) throws IOException {
        if (file != null) {        // 获取文件流，解析文件
            InputStream textIn = file.getInputStream();
            InputStreamReader read = new InputStreamReader(textIn, "UTF-8"); // 考虑到文本编码
            BufferedReader bf = new BufferedReader(read);
            String line = null;
            String s[] = null;
            StringBuffer errCode = new StringBuffer();
            StringBuffer conflicCode = new StringBuffer();
            List<SectionCode> insertList = new ArrayList<>();
            List<String> codeAll = new ArrayList<>();
            List<Section> sts = sectionDao.retrieveList();
            Map<String, Long> ksNameAndSectionId = new HashMap<>();
            //获取所有已经存在的科室名称对应编号
            for (Section st : sts) {
                ksNameAndSectionId.put(st.getName(), st.getId());
            }
            InputStream inputStream = file.getInputStream();
            Workbook workbook = new XSSFWorkbook(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
            nextRow:
            for (Row row : sheet) {

                String code = getCellNum(row, 0);
                String std = getCellNum(row, 1);
                String name = getCellNum(row, 2);
                if (StringUtils.isNotBlank(code)) {
                    //校验科室code的格式
                    String[] codeTemp = code.split("\\.");
                    for (int j = 0; j < codeTemp.length; j++) {
                        if (!codeTemp[j].matches("^[0-9]+$")) {
                            if (errCode.length() == 0) {
                                errCode.append("该记录code格式有误:");
                            }
                            errCode.append(code + "," + std + "," + name + ";");
                            continue nextRow;
                        }
                    }
                    //校验code是否重复
                    if (codeAll.contains(code)) {
                        if (conflicCode.length() == 0) {
                            conflicCode.append("code重复:");
                        }
                        conflicCode.append(code + ";");
                    } else {
                        codeAll.add(code);
                    }
                } else {
                    if (errCode.length() == 0) {
                        errCode.append("该记录code格式有误:");
                    }
                    errCode.append(code + "," + std + "," + name + ";");
                    continue nextRow;
                }
                SectionCode value = new SectionCode();
                value.setModifierId(user.getUserId() + "");
                value.setSectionCode(code);
                if (StringUtils.isBlank(name)) {
                    value.setSectionId("0");
                } else if (ksNameAndSectionId.get(name) != null) {
                    value.setSectionId(ksNameAndSectionId.get(name) + "");
                } else {
                    //不存在需要新增
                    Section value1 = new Section();
                    value1.setCnt(1);
                    value1.setDisable("0");
                    value1.setModifierId(user.getUserId());
                    value1.setName(name);
                    value1.setSexAgeFlag(0);
                    value1.setSex(0);
                    value1.setAge("");
                    Long sectionId = sectionDao.insert(value1);
                    ksNameAndSectionId.put(name, sectionId);
                    value.setSectionId(sectionId + "");
                }
                value.setStd(std);
                insertList.add(value);
            }
            if (errCode.length() > 0 || conflicCode.length() > 0) {
                //如果失败,删除有可能添加的section的记录
                sectionDao.deleteSectionInvalid();
                Map<String, Object> map = new HashMap<>();
                ReturnCode returnCode = ReturnCode.DYNAMIC_DESC_EXCEPTION;
                returnCode.setDesc(errCode + "\n" + conflicCode + "\n");
                return new ReturnData(returnCode, map);
            }
            if (insertList.size() > 0) {
                sectionCodeDao.deleteAll();
                sectionCodeDao.batchInsert(insertList);
            }
            if (bf != null) {
                bf.close();
            }
            if (read != null) {
                read.close();
            }
            //校验国家对应科室是否在科室图片名称中
            checkData();
            //如果失败,删除有可能添加的section的记录
            sectionDao.deleteSectionInvalid();
            return ReturnUtil.success("成功");
        } else {
            ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
            rc.setDesc("文件有误");
            return ReturnUtil.fail(rc);
        }
    }

    public void deleteWarn(String id, User user) {
        staticDataDao.deleteWarn(id);
    }
}
